package com.zzh.custom.loading;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Shader;
import android.graphics.drawable.ShapeDrawable;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.LinearInterpolator;

import androidx.annotation.NonNull;

import com.zzh.custom.R;

import java.util.ArrayList;
import java.util.List;

public class OngoingView extends View {

    private String TAG = OngoingView.class.getSimpleName();

    private int[] mColors = new int[]{
            Color.parseColor("#e1e1e1"),
            Color.parseColor("#c0ffc0"),
            Color.parseColor("#e1e1e1"),
            Color.parseColor("#c0ffc0"),
            Color.parseColor("#e1e1e1"),
            Color.parseColor("#c0ffc0"),
            Color.parseColor("#e1e1e1"),
            Color.parseColor("#c0ffc0"),
            Color.parseColor("#e1e1e1"),
            Color.parseColor("#c0ffc0"),
    };
    private float[] mPositions = new float[]{
            0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f
    };

    private Paint mPaint = new Paint();
    private Shader mShader;
    private Matrix mMatrix = new Matrix();
    private int mMaxLength = 0;
    private ValueAnimator mValueAnimator;

    private List<Path> mPaths = new ArrayList<>();

    public OngoingView(Context context) {
        super(context);
        setClickable(true);
        mPaint.setAntiAlias(true);
        initValueAnimator();
    }

    private void initValueAnimator() {
        mValueAnimator = ValueAnimator.ofFloat(0, 1f);
        mValueAnimator.setDuration(5000);
        mValueAnimator.addUpdateListener(animation -> {
            float value = (float) animation.getAnimatedValue();
            mMatrix.setTranslate(mMaxLength * value, mMaxLength * value);
            if (mShader != null) {
                mShader.setLocalMatrix(mMatrix);
            }
            invalidate();
        });
        mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        mValueAnimator.setInterpolator(new LinearInterpolator());
        getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                getViewTreeObserver().removeOnGlobalLayoutListener(this);
                mValueAnimator.start();
            }
        });
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (getWidth() <= 0) return;
        for (Path path : mPaths) {
            canvas.drawPath(path, mPaint);
        }
        if (mPaths.size() <= 0) {
            canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);
        }
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        if (visibility == View.VISIBLE) {
            if (mValueAnimator != null) {
                if (!mValueAnimator.isRunning()) {
                    mValueAnimator.start();
                }
            }
        } else {
            if (mValueAnimator != null) {
                if (mValueAnimator.isRunning()) {
                    mValueAnimator.end();
                }
                mValueAnimator = null;
            }
        }
    }

    public void configOperationView(View rootView) {
        mPaths.clear();
        if (isAllowAddOngoing(rootView)) {
            mPaths.add(createRootPath(rootView));
        } else if (rootView instanceof ViewGroup) {
            List<Path> list = createPath((ViewGroup) rootView, 0, 0);
            if (list != null && list.size() > 0) {
                mPaths.addAll(list);
            }
        }
    }

    private Path createRootPath(View view) {
        Path path = new Path();
        path.moveTo(0, 0);
        path.lineTo(0, view.getHeight());
        path.lineTo(view.getWidth(), view.getHeight());
        path.lineTo(view.getWidth(), 0);
        return path;
    }

    private List<Path> createPath(ViewGroup viewGroup, int preLeft, int preTop) {
        int count = viewGroup.getChildCount();
        if (count == 0) return null;
        List<Path> list = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            View view = viewGroup.getChildAt(i);
            if (isAllowAddOngoing(view)) {
                list.add(createPath(view, preLeft, preTop));
            } else if (view instanceof ViewGroup) {
                List<Path> paths = createPath((ViewGroup) view,
                        view.getLeft() + preLeft,
                        view.getTop() + preTop);
                if (paths != null && paths.size() > 0) {
                    list.addAll(paths);
                }
            }
        }
        return list;
    }

    private Boolean isAllowAddOngoing(View view) {
        if (view instanceof LoadingTag) {
            LoadingTag loadingTag = (LoadingTag) view;
            return loadingTag.isAllowOngoing();
        }
        return false;
    }

    private Path createPath(View view, int preLeft, int preTop) {
        Path path = new Path();
        path.moveTo(view.getLeft() + preLeft, view.getTop() + preTop);
        path.lineTo(view.getLeft() + preLeft, view.getBottom() + preTop);
        path.lineTo(view.getRight() + preLeft, view.getBottom() + preTop);
        path.lineTo(view.getRight() + preLeft, view.getTop() + preTop);
        return path;
    }


    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (getMeasuredWidth() > 0) {
            mMaxLength = getMeasuredWidth() > getMeasuredHeight() ? getMeasuredWidth() : getMeasuredHeight();
            mMatrix.setTranslate(mMaxLength, mMaxLength);
            mShader = mPaint.setShader(new LinearGradient(0, 0,
                    mMaxLength,
                    mMaxLength,
                    mColors, mPositions, Shader.TileMode.MIRROR));
            mShader.setLocalMatrix(mMatrix);
        }
    }

}
